package com.service.bracelet.security;

import com.service.bracelet.common.CacheManager;
import com.service.bracelet.entity.User;
import com.service.bracelet.util.JwtTokenUtil;
import com.service.bracelet.util.UtilConsts;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * JWT登录授权过滤器
 * Created by macro on 2018/4/26.
 */
public class LoginFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.addHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client");

        // 允许跨域访问
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            chain.doFilter(request, response);
            return;
        }

        // 验证token
        String authToken = JwtTokenUtil.getToken(request);
        if (StringUtils.isNotBlank(authToken)) {
            User user = CacheManager.get(authToken, request);
            String account = JwtTokenUtil.getUserAccount(authToken);
            if (StringUtils.isBlank(account)) {
                this.writeError(response, "不是有效token，请重新登录!");
            } else if (user == null || StringUtils.isBlank(user.getAccount())) {
                this.writeError(response, "登录超时，请重新登录!");
            } else if (!account.equals(user.getAccount())) {
                this.writeError(response, "验证token失败，请重新登录!");
            } else {
                chain.doFilter(request, response);
                return;
            }
        }
        String verifyToken = JwtTokenUtil.getVerifyToken(request);
        String uri = request.getRequestURI();
        if (StringUtils.isNotBlank(verifyToken)) {
            if (ArrayUtils.contains(UtilConsts.SECURITY_ALLOW_VERIFY_URLS, uri)) {
                chain.doFilter(request, response);
            } else {
                this.writeError(response, "修改密码中，无法访问其他链接！");
            }
            return;
        }
        if (!ArrayUtils.contains(UtilConsts.SECURITY_ALLOW_ACCESS_URLS, uri)) {
            this.writeError(response, "未登录");
        } else {
            chain.doFilter(request, response);
        }
    }

    private void writeError(HttpServletResponse response, String message) throws IOException {
        response.setStatus(401);
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/json; charset=utf-8");
        ServletOutputStream os = response.getOutputStream();
        IOUtils.write("{\"code\":401,\"message\":\"" + message + "\"}", os, "utf-8");
    }
}
